﻿using System;
using System.Collections;
using System.Data;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using SLS.Base;
using SLS.Document;
using SLS.ExClassLib.Database;
using SLS.ExClassLib.Event;
using SLS.ExClassLib.Events;
using SLS.ExClassLib.ExThreading;
using SLS.ExClassLib.Message;
using SLS.ExClassLib.WCFClient;
namespace SLS.Core.HLASimu
{
    public class WFFederate : Federate
    {
        public WFFederate()
            : base()
        {
        }
        public WFFederate(string m_ClientType, string m_FEDName, object m_RTIServiceClient)
            : base(m_ClientType, m_FEDName, m_RTIServiceClient)
        {

        }
        public override void work_ChangedWorkItemState(object sender, ChangedWorkItemStateEventArgs e)
        {
            base.work_ChangedWorkItemState(sender, e);
            lock (this)
            {
                ExWorkItem exItem = (ExWorkItem)e.WorkItem;
                WorkItemState state = exItem.State;
                if (state == WorkItemState.Completed)
                {
                    MessageEx msg = exItem.ThisMessage;
                    string JobType = msg.JobType;
                    if (JobType == "WF2UI")
                    {
                        Application.Current.Dispatcher.BeginInvoke(m_ReceiveMessage, DispatcherPriority.ContextIdle, msg);
                    }
                    if (JobType == "UI2WF")
                    {
                        Application.Current.Dispatcher.BeginInvoke(m_SendMessage, DispatcherPriority.ContextIdle, msg);
                    }
                    if (JobType == "UI2WC")
                    {
                        ClientWFService.Instance.SendWFMessage(msg);
                    } 
                }
            }
        }
        public override void SendMessage(MessageEx msg)
        {
            try
            {
                base.SendMessage(msg);
                ClientWFService.Instance.RegisterMessage(msg);
                base.ReceiveMessage(msg);
                MessageEx msgA = EventDispatcher.Instance.MessagePool.Find(msg.MessageID_Req);
                if (msgA != null)
                {
                    msg = EndUpMessage(msgA, msg);
                }
                POPWFMessage();  
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public override void ReceiveMessage(MessageEx msg)
        {
            try
            {
                Tracer.Info("RTI:" + FEDName, " received message " + msg.JobID + " with timestamp" + msg.TimeStamp);
                ClientWFService.Instance.RegisterMessage(msg);
                base.ReceiveMessage(msg);
                MessageEx msgA = EventDispatcher.Instance.MessagePool.Find(msg.MessageID_Req);
                if (msgA != null)
                {
                    msg = EndUpMessage(msgA, msg);
                }
                POPWFMessage();  
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        private void POPWFMessage()
        {
            try
            {
                //GetMessage();
                //return ;
                //Task t = Task.Factory.StartNew(() => { msg=GetMessage(); });
                this.Dispatcher.BeginInvoke
                    (
                    () => { 
                        GetMessage(); 
                    }, 
                    DispatcherPriority.Normal
                    );
                //MessagePool按时间戳排序
                //获取最小时间戳消息
                //获取服务器上此联邦成员最小时间戳MinTimeStamp
                //如果当前时间戳=最小时间戳，则处理这个消息，否则等待下一个消息到达或者处理完消息之后再触发

            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public override ArrayList GetMessage(bool FIFO = true)
        {
            ArrayList msgList = base.GetMessage(FIFO); 
            foreach (MessageEx msg in msgList)
            {
                if (msg != null)
                {
                    SLBC doc = null;//sun20121002
                    doc = (SLBC)DocumentManagement.Instance.FindDocumentByAddress(FEDName,"");
                    if (doc != null)
                    {
                        doc.ProcessWFMessage(msg);
                        doc._uiSyncContext = SynchronizationContext.Current;
                    }
                }
            }
            return msgList;
        }
        public override void BuildWorkQueue(MessageEx msg)
        {
            base.BuildWorkQueue(msg); 
        }
        public override void MakeUpMessage(string CallerType, ref MessageEx msg, object Data = null,string Action="")
        {
            base.MakeUpMessage(CallerType, ref msg, Data,Action);  
            switch (Action)
            {
                case "OnGetNextMessage":
                    msg.JobType = "FED2RTI";
                    POPWFMessage();
                    break; 
                case "OnFinishQuery":  
                    break;
                case "OnSelectedRecordEdit":
                case "OnValidateRecord":
                case "OnStartWorkFlow": 
                default: 
                    break;
            }            
        }
        public override MessageEx EndUpMessage(MessageEx msgA, MessageEx msgB)
        {
            string MessageID_Req = msgB.MessageID_Req;
            MessageEx msgC;
            if (EventDispatcher.Instance.MessagePool.MessageStock.ContainsKey(MessageID_Req))
            {
                msgC = EventDispatcher.Instance.MessagePool.MessageStock[MessageID_Req].msg;
                msgB.setEvent = new DataSet();
                msgB.MessageID_Req = msgB.MessageID;
                //查询结果
                if (msgB.setEvent != null)
                {
                    msgB.setEvent.Merge(msgC.setEvent);
                }
                //依据何种条件，得到这个结果
                if (msgC.setEvent != null)
                {
                    foreach (DataTable dtTmp in msgC.setEvent.Tables)
                    {
                        if (!msgB.setEvent.Tables.Contains(dtTmp.TableName))
                        {
                            msgB.setEvent = (DataSet)DataAccessService.Instance
                                .ImportDataTable(msgB.setEvent, dtTmp);
                        }
                    }
                }
            }

           return base.EndUpMessage(msgA, msgB);
        }
    }
}
